Quote Retention & Reuse

When a quote request succeeds, the system stores it keyed by the combination of contact.email and contact.ratingZipCode.

How Retrieval Works

  • If a NEW email/zip pair is used, a fresh quote record is created and returned.
  • If the SAME email/zip pair was previously quoted, the existing quote is transitioned into a “return” state and replaced with the new request data.

Pet & Coverage Replacement

  • All prior pets and coverage selections tied to that email/zip pair are removed.
  • The pets and coverages from the latest request fully replace the old ones—there is no merge.
  • This ensures partners can safely re-post the same pet (idempotent for unchanged data) or update details without manually clearing prior state.

Typical Partner Flow

  1. Partner collects pet + contact info and posts initial quote.
  2. Partner later re-issues a quote (e.g., user revisits) with identical or updated pet information.
  3. The platform returns the updated quote reflecting ONLY the newest pets and coverage selections.

Because a coverage is often not yet finalized at first interaction, re-quoting with the same pet details effectively refreshes pricing without unexpected historical carryover.

Implications

  • Do not rely on earlier pets persisting if you omit them in a subsequent request—always send the authoritative full set you want represented.
  • To remove a pet, simply exclude it from the next quote request payload.
  • If you need historical comparisons, store snapshots on your side before re-posting.

Best Practices

  • Always treat the quote request body as the complete desired state for pets & coverage selections.
  • Cache the current quoteId client-side, but be prepared for a refreshed response returning the same or a new quoteId depending on system logic.
  • Log re-quote events (email/zip reuse) for analytics on user revisit behavior.

Analytics Fields

Field path: top-level object key: analytics

The analytics block allows attaching campaign attribution metadata to the quote record. It is treated as a full replacement object each time you POST or re‑POST a quote (or use any endpoint that accepts it). If you omit analytics on an update (even if it was present previously), the previously stored analytics values are cleared / overwritten.

Property Required Source Description Example
medium Yes Provided by Embrace Marketing medium classification used for partner channel attribution. affiliate-network
term No Partner defined Freeform term for internal ad keyword / sub-channel segmentation. spring-keyword-1
content No Partner defined Distinguishes creative variations (A/B test, banner vs. text). banner-300x250
campaign No Partner (runtime) Your campaign / promo / slogan identifier. spring-2025-launch
source Yes Provided by Embrace High-level traffic source identifier allocated by Embrace. partner-portal

Overwrite Semantics

  • Full Replacement: The server does not merge partial analytics objects. Send ALL desired fields every time you submit a quote request.
  • Omission = Clear: Leaving out the analytics block (or a specific field inside it) when re‑posting will result in that data no longer being associated with the current quote state.
  • Consistency: For multi-step journeys (add pet, update coverage, change frequency) persist and resend the same analytics object unless intentionally changing attribution.

Best Practices

  • Persist analytics client‑side (e.g., localStorage/session) after first submission so later modifications can resend it reliably.
  • Validate required keys (medium, campaign, source) before initial submission; reject empty strings.
  • Avoid PII—these fields are for attribution only.
  • Normalize casing (e.g., lower-kebab) for easier downstream aggregation.
  • Log original + updated analytics values around each POST for audit.

Minimal Example With Analytics

{
  "analytics": {
    "medium": "affiliate-network",
    "term": "keyword-group-a",
    "content": "banner-1",
    "campaign": "spring-2025-launch",
    "source": "partner-portal"
  },
  "contact": { "ratingZipCode": "44114", "email": "owner@example.com", "brand": "embrace" },
  "pets": [ { "name": "Riley", "breedId": 452, "gender": "Female", "age": "Two" } ]
}

Example: Unintentionally Clearing Analytics

If the initial request included analytics (above) but a later update omits it:

{
  "contact": { "ratingZipCode": "44114", "email": "owner@example.com", "brand": "embrace" },
  "pets": [ { "name": "Riley", "breedId": 452, "gender": "Female", "age": "Two" } ]
}

Result: Stored analytics attribution will be cleared for the quote.

Payment Frequency

Field path: contact.billingInformation.paymentFrequency

Accepted values (exact capitalization required):

  • "Monthly" (default when omitted) – Premium fields reflect the month-to-month billing scenario (e.g., monthlyPremium, paymentDueRecurring).
  • "Yearly" – The SAME premium fields are reused to represent the full annual amounts (no separate annual field names introduced).

If you omit the field the API assumes Monthly. Use Yearly to present a single pay‑in‑full option; only your UI labels change.

Need to change the payment frequency after quoting without rebuilding the entire payload? Use the lightweight Update Payment Frequency endpoint.

Minimal Example (Monthly default)

{
  "contact": {
    "ratingZipCode": "44114",
    "email": "owner@example.com",
    "phoneNumber": "555-123-1234",
    "brand": "embrace"
  },
  "pets": [
    { "name": "Riley", "breedId": 452, "gender": "Female", "age": "Two" }
  ]
}

Explicit Yearly Example

{
  "contact": {
    "ratingZipCode": "44114",
    "email": "owner@example.com",
    "phoneNumber": "555-123-1234",
    "brand": "embrace",
    "billingInformation": {
  "paymentFrequency": "Yearly"
    }
  },
  "pets": [
    { "name": "Riley", "breedId": 452, "gender": "Female", "age": "Two" }
  ]
}

UI Guidance

  • Provide a toggle (Monthly / Annual) before quote submission so you only need one API call per mode.
  • Cache the last-used frequency in local storage or session to persist user preference.

Validation Notes

  • Only accept Monthly or Yearly; reject or default any other casing/values.
  • Switching between modes requires only relabeling in the UI—no different field extraction.
  • If an unsupported value is sent, expect validation failure; sanitize before calling the API.
  • For pre-validating address/email inputs before quoting, see Validation Endpoints.

Rate Shopping Overview

rateShopCoverageSelections lets you ask the API to price (“rate shop”) specific coverage combinations up front.

Result Location: The calculated results are returned in the top-level rateShopQuoteResults array of the QuoteResponse. Each element corresponds positionally to a coverage selection you sent (index-aligned with the input array) and contains its own coverageSelection, premiumSummary, and petCoverages.

Authoritative schema (always check for newest values): CoverageSelection Definition

Each element in rateShopCoverageSelections represents one coverage configuration you want premium data for. The API responds with the calculated premiums, allowing you to build a coverage picker without making multiple quote calls.

Accepted Value Forms

For the four primary numeric/enum style fields you may pass either:

  1. The canonical word form (e.g., FourHundredFifty), OR
  2. The numeric form AS A STRING (e.g., "450").

Important: Send both forms as JSON strings. Do not send bare numbers (e.g., 450 without quotes). The API accepts the numeric variant only when provided as a string token.

For the authoritative, most current list of allowed values (and any future additions), always refer to the live schema: CoverageSelection Definition

Field String Forms Numeric Forms Notes
reimbursementPercentage Seventy, Eighty, Ninety "70", "80", "90" Percent of eligible costs reimbursed
annualWellnessReward None, TwoHundredFifty, ThreeHundred, FourHundredFifty, FiveHundred, SixHundredFifty, SevenHundred "0", "250", "300", "450", "500", "650", "700" None/"0" = no wellness add‑on
annualDeductible OneHundred, TwoHundred, TwoHundredFifty, ThreeHundred, FiveHundred, SevenHundredFifty, OneThousand "100", "200", "250", "300", "500", "750", "1000" Deductible before reimbursement
annualReimbursementLimit TwoThousand, FiveThousand, EightThousand, TenThousand, FifteenThousand, ThirtyThousand, Unlimited "2000", "5000", "8000", "10000", "15000", "30000", "-1" Unlimited represented as "-1"

Boolean flags: examFeeCoverage, drugDentalCoverage (true / false).

Example Request Fragment

{
  "rateShopCoverageSelections": [
    {
      "reimbursementPercentage": "Eighty",
      "annualWellnessReward": "450",
      "annualDeductible": "500",
      "annualReimbursementLimit": "Unlimited",
      "examFeeCoverage": true,
      "drugDentalCoverage": false
    },
    {
      "reimbursementPercentage": "90",
      "annualWellnessReward": "None",
      "annualDeductible": "300",
      "annualReimbursementLimit": "15000",
      "examFeeCoverage": false,
      "drugDentalCoverage": true
    }
  ]
}

Interpreting Results

Each element in rateShopQuoteResults contains:

  • coverageSelection – Echo of the selection that was rated.
  • premiumSummary – Pricing snapshot for that combination.
  • petCoverages – Per-pet pricing details.

Example response fragment:

{
  "rateShopQuoteResults": [
    {
      "coverageSelection": {
        "reimbursementPercentage": "Eighty",
        "annualDeductible": "500",
        "annualReimbursementLimit": "Unlimited",
        "annualWellnessReward": "450",
        "examFeeCoverage": true,
        "drugDentalCoverage": false
      },
      "premiumSummary": { /* ...pricing fields... */ },
      "petCoverages": [ /* per-pet details */ ]
    }
  ]
}

Best Practices

  • Request no more than 50 combinations per call (practical UI performance + payload size).
  • Persist rateShopQuoteResults client-side to avoid unnecessary re-quotes during a single user session.

Validation & Re-Quote Triggers

  • Validate string tokens (avoid typos like Seventyy).
  • Reject unsupported numeric strings (e.g., "475").
  • Make a new POST request to the fullquote endpoint when pets change, a new combination is needed, or data is stale.